import java.util.Arrays;
/**
 * 1.数组
 *  1.1二维数组
 *
 * 2.类和对象
 *  2.1面向对象的初步认知
 *  2.2类的定义和使用
 *  2.3类的实例化
 *  2.4this引用
 *  2.5对象的构造及其初始化
 */

/**
 * 2.3类的实例化
 *  1.什么是实例化
 *  2.类和对象说明
 *  3.类的几个注意点
 */

/**
 * 2.2类的定义和使用
 * 1.什么是类 : 类是对象的具体描述
 *
 * 2.类的定义格式: class className { field类的属性 method类的方法}
 * 注 1.类名定义规则->大驼峰
 *  2.属性->先默认加public
 *  3.一个文件中一班值定义一个类
 *  4.文件中,只有一个public 修饰的类
 *  5.类名,必须与文件名相同
 *  6.修改类名通过->右键文件 -> refactor->RenameFile,如果文件内,类不止一个时,修改类名,会报错(编译器无法区分要改那个类)
 */

/**
 * 定义狗类
 */
class Dog {
    /**
     * 狗的成员属性
     */
    public String name;
    public int age;
    public String color;
    /**
     * 狗的成员方法
     */
    public void barks() {
        System.out.println(name + "汪汪汪~~");
    }
    public void wag() {
        System.out.println(name + "摇尾巴~~");
    }
}

/**
 * 2.2类的定义格式
 */
class WashMachine {
    /**
     * 类的属性 成员变量 字段
     */
    public String brand; // 品牌
    public String type; // 型号
    public double weight; // 重量
    public double length; // 长
    public double width; // 宽
    public double height; // 高
    public String color; // 颜色

    /**
     * 类的方法
     * 在类中定义时,方法修饰符使用public
     */
    public void washClothes() { // 洗衣服
        System.out.println("洗衣功能");
    }
    public void dryClothes() { // 脱水
        System.out.println("脱水功能");
    }
    public void setTime() { // 定时
        System.out.println("定时功能");
    }
}
class MyValue {
    public int val;
}

/**
 * 日期
 *
 */
class Date {
    /**
     * 成员变量 属性 字段
     * 默认初始化,查表即可,引用类型为null
     */
    public int year;
    public int month;
    public int day;
    /**
     * 就地初始化
     */
//    public int year = 1000;
//    public int month = 2;
//    public int day = 20;

    /**
     * 构造方法
     * 1.名字与类名相同,没有返回值
     * 2.一般由public修饰
     * 3.在编译器new对象时,编译器自动调用
     */

    public Date() {
//        this.year = 2005;
//        this.month = 3;
//        this.day = 1;

       this(2005,3,1);//this(),this访问构造方法

        System.out.println("调用不带参数构造方法");
    }

    public Date(int year,int month,int day) {
        //this();//不支持循环调用(即你调用我,我调用你)
        this.year = year;
        this.month = month;
        this.day = day;

        System.out.println("调用带参数构造方法");
    }
    /**
     * 成员方法
     */
    public void setDate(int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public void printDate() {
        System.out.println("年: " + this.year + "月: " + this.month + "日: " + this.day);
        this.func();
    }

    public void func() {
        System.out.println("hehe");
    }
}
public class Test {
    /**
     * 对象的构造及其初始化
     *  1.构造方法
     *  2.默认初始化
     *  3.就地初始化
     */
    public static void main(String[] args) {
        /**
         *  就地初始化
         *  1.类内创建成员变量时,直接给初始值
         */

    }

    public static void main13(String[] args) {
        /**
         * 默认初始化
         *  创建实例,变量为默认值
         */
    }
    public static void main12(String[] args) {
        /**
         * 构造方法
         *  概念: 特殊的成员方法,方法名与类型名相同,在创建对象时,由编译器自动调用,并且在整个周期只调用一次
         *  初始化: 构造方法初始化(可以重载)
         *  特性:
         *  1.构造方法名与类名相同,并且没有返回值
         *  2.构造方法名只执行一次,且是在创建实例时,编译器自动调用
         *  3.构造方法可以重载
         *  4.如果用户没有定义构造方法,编译器会自动生成一个构造方法
         *  5.构造方法不能形成环(即相互调用)
         *  6.构造方法,可以使用this调用其他方法来简化代码.this()调用必须是第一条语句
         *  7.绝大多数情况下,使用public修饰,特殊情况下,使用private修饰
         */
        Date date1 = new Date();//不带参数的构造方法

        date1.printDate();

        Date date2 = new Date(2005,3,1);//编译器自动调用带参数的构造方法

        date2.printDate();
    }

    /**
     * 2.4this引用
     * @param args
     *  为什么要有this引用
     *      1.变量名与形参名相同情况
     *      2.通过this引用指向对象(谁调用this,谁就是其指向的对象)
     *  this引用是什么
     *      指向对象进行访问
     *  this引用特性
     *      1.this的类型,对应指向对象类型,谁调用,就指向谁
     *      2.this只能在成员方法中使用
     *      3.this,只能指向当前对象,不能再引用其它对象(即,同一时刻内,只能指向调用它的对象)
     *      4.this其实是一个参数,不过被编译器隐藏了,证明了谁调用,就指向谁(相当于,是在使用参数)
     *
     *      this的三个用法
     *      this.成员变量 访问成员变量
     *      this.成员方法 访问成员方法
     *      this() 调用当前类构造方法
     */
    public static void main11(String[] args) {
        Date date1 = new Date();

        date1.setDate(1940,5,1);
        date1.printDate();

        Date date2 = new Date();

        date2.setDate(1900,2,13);
        date2.printDate();
    }

    /**
     * 交换变量->通过类来实现
     * @param args
     */
    public static void swap(MyValue myValue1,MyValue myValue2) {
        int tmp = myValue1.val;
        myValue1.val = myValue2.val;
        myValue2.val = tmp;
    }
    public static void main10(String[] args) {
        MyValue myValue1 = new MyValue();
        myValue1.val = 10;

        MyValue myValue2 = new MyValue();
        myValue2.val = 20;

        System.out.println("打印前myValue1: " + myValue1.val);
        System.out.println("打印前myValue2: " + myValue2.val);

        swap(myValue1,myValue2);

        System.out.println("打印后myValue1: " + myValue1.val);
        System.out.println("打印后myValue2: " + myValue2.val);
    }
    public static void main9(String[] args) {
        /**
         * 类和对象的说明
         * 1.类只是一个模型,即一个实体的抽象描述
         * 2.类是一种自定义类型,可以用来定义变量
         * 3.类可以new多个实例
         *
         * 注 1.引用不能指向引用,而是多个引用可以指向一个对象
         * 2.一个引用不能同时指向多个对象
         * 3.引用为null,代表该引用不指向任何对象
         */
    }
    public static void main8(String[] args) {
        /**
         * 1.什么是实例化
         * 用类类型创建对象的过程，称为类的实例化
         * 类名相当于新类型,通过new来实例化
         * 注: 1.new关键字用于创建一个对象的实例
         * 2.使用.号访问类内属性和方法
         * 3.同一个类可以创建多个实例
         */
        Dog dog1 = new Dog();

        dog1.name = "大黄";
        dog1.age = 2;
        dog1.color = "黄色";

        System.out.println("姓名: " + dog1.name);
        System.out.println("年龄: " + dog1.age);
        System.out.println("颜色: " + dog1.color);

        dog1.barks();
        dog1.wag();

        Dog dog2 = new Dog();

        dog2.name = "小灰";
        dog2.age = 3;
        dog2.color = "灰色";

        System.out.println("姓名: " + dog2.name);
        System.out.println("年龄: " + dog2.age);
        System.out.println("颜色: " + dog2.color);

        dog1.barks();
        dog1.wag();
    }
    public static void main7(String[] args) {
        /**
         * 类的定义和使用
         */
    }

    /**
     * 2.1面向对象的初步认知
     * 1.什么是面向对象
     * 2.面向对象和面向过程
     */
    public static void main6(String[] args) {
        /**
         * 面向对象和面向过程
         * 面向对象: 对象之间进行交互,不关注对象怎么做(将大象放进冰箱,打开冰箱->把大象放进去->关闭对象)
         * 面向过程: 着重于过程,要知道具体过程,如何做....(传统洗衣服)
         */
    }
    public static void main5(String[] args) {
        /**
         * 什么是面向对象
         * 面向对象是解决问题的一种思想，主要依靠对象之间的交互完成一件事情
         * 万物皆可为对象
         */
    }
    /**
     * 二维数组
     * @param args
     * 二维数组的创建和初始化
     * 二维数组的遍历
     * 不规则数组
     */
    /**
     * 不规则数组
     * 静态初始化时,列元素个数不等
     * 动态初始化,不指定列,通过引用变量来new初始化(即以一维数组形式进行初始化,不过其精简用法不能使用)
     */

    public static void main4(String[] args) {
        int[][] array = new int[4][];

        array[0] = new int[10];//一维数组动态初始化
        array[1] = new int[]{1,2,34};
        array[2] = new int[]{3,4,6,5,10};

        int[][] array2 = {{1,2,3,4,5},{7,8,9,10,11,12,14}};
    }

    /**
     * 二维数组的遍历
     * for循环
     * for-each循环
     * 数组转字符串
     */
    public static void main3(String[] args) {
        /**
         * for循环
         * 数组名.length,是求行数
         * 本质上,二维数组其实是不同行的引用变量,指向了一个一维数组起始地址,通过进行变量操作遍历一维数组
         * 所以一维数组.length,就可以求到列个数
         */
        int[][] array = {{1,2,3},{4,5,6},{7,8,9}};

        for(int i = 0;i < array.length;i++) {
            for(int j = 0;j < array[i].length;j++) {
                System.out.print(array[i][j] + " ");
            }
            System.out.println();
        }

        /**
         * for-each(数组内元素类型定义的变量:数组名)
         */
        for (int[] tmpArray : array) {
            for(int x : tmpArray) {
                System.out.print(x + " ");
            }
            System.out.println();
        }

        /**
         * 数组转字符串
         * deepToString(二维数组名)以字符串形式打印二维数组
         */
        System.out.println(Arrays.deepToString(array));
    }
    /**
     * 二维数组的创建和初始化
     * @param args
     */

    public static void main2(String[] args) {
        /**
         * 二维数组的初始化
         * 静态初始化
         *  1.数组类型[][] 数组名 = new 数组类型[][]{初始化数据}
         *  2.数组类型[][] 数组名 = {初始化数据}
         *  注:1.初始化数据时,行内值使用{}存放,行之间使用","号隔开
         *     2.其它规则如一维数组
         * 动态初始化
         *  数组类型[][] 数组名 = new 数组类型[行数][列数(可以省略)];
         */

        int[][] array1 = {{1,2,3},{4,5,6},{7,8,9}};

        int[][] array2 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};

        int[][] array3 = new int[10][5];
        int[][] array4 = new int[10][];//证明行没有指向任何对象,打印为null,可以定义其内一维数组
    }
    public static void main1(String[] args) {
        /**
         * 二维数组的创建
         * 数组内元素类型[][] 数组名 = new 数组内元素类型[行数][列数]
         * 注:1.因为数组是引用类型,它指向了对象的起始地址.才能通过行找到列值
         * 2.二维数组是特殊的一维数组
         */

        int[][] array1 = new int[5][10];//完整的创建

        int[][] array2 = new int[5][];//省略列数

//        int[][] array3 = new int[][10];//error 不能省略行
    }
}
